package com.ican.oc.datasyn;


import java.io.File;
import java.util.Date;
import java.util.List;

import javax.annotation.Resource;

import org.htmlcleaner.HtmlCleaner;
import org.htmlcleaner.TagNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import com.ican.common.SystemConstants;
import com.ican.domain.product.Category;
import com.ican.domain.product.Option;
import com.ican.domain.product.OptionValue;
import com.ican.domain.product.Product;
import com.ican.domain.product.ProductAttribute;
import com.ican.domain.product.ProductImage;
import com.ican.nc.ParseUtil;
import com.ican.oc.domain.OcCategory;
import com.ican.oc.domain.OcCategoryDescription;
import com.ican.oc.domain.OcProduct;
import com.ican.oc.domain.OcProductDescription;
import com.ican.oc.domain.OcProductImage;
import com.ican.oc.domain.OcProductOption;
import com.ican.oc.domain.OcProductOptionValue;
import com.ican.oc.domain.OcProductToCategory;
import com.ican.oc.service.OcProductService;
import com.ican.service.product.OptionAndValueService;
import com.ican.service.product.ProductService;
import com.ican.util.CalculateUtil;
import com.ican.util.FileUtils;
import com.ican.util.ValidateUtil;

@Service("ocDataSynService")
public class OcDataSynService{
    private Logger logger = LoggerFactory.getLogger(OcDataSynService.class);

    private ProductService productService;
    private OptionAndValueService optionAndValueService;
    
    private OcProductService ocProductService;
    
    public void dataSynAuto(){
        //提取所有未更新或者更新时间比同步时间晚的类目
        List<Integer> categoryIds = productService.findAllCategoryIdsToSynAuto();
        if(categoryIds == null || categoryIds.size() < 1){
            return;
        }
        for(Integer categoryId : categoryIds){
            int flag = synCategory(categoryId, true);
            if(SystemConstants.ENTITY_DATE_SYN_STATUS_SUCCESS == flag){
                synProductByCategory(categoryId, true);
            }
        }
    }
    
    public int synCategory(Integer categoryId, boolean isAuto){
        Category category_t = productService.findCategory(categoryId);
        if(category_t.getSynStatus() == SystemConstants.ENTITY_DATE_SYN_STATUS_RUN){
            return SystemConstants.ENTITY_DATE_SYN_STATUS_RUN;
        }
        if(isAuto && category_t.getSynStatus() == SystemConstants.ENTITY_DATE_SYN_STATUS_SUCCESS && 
                    category_t.getSynTime().after(category_t.getModifyTime())){
            return SystemConstants.ENTITY_DATE_SYN_STATUS_SUCCESS;
        }
        try{
            productService.updateCategorySynStatus(category_t.getId(), SystemConstants.ENTITY_DATE_SYN_STATUS_RUN);
            Integer cid_oc = category_t.getSynCategoryId();
            if(cid_oc == null){//未同步过
                OcCategory ocCategory = new OcCategory(new Date());
                //中文
                OcCategoryDescription ocCateDesc_ch = new OcCategoryDescription(ocCategory.getCategoryId(), SystemConstants.LANG_ID_CN, category_t.getName(), category_t.getDescription());
                //原文
                OcCategoryDescription ocCateDesc = new OcCategoryDescription(ocCategory.getCategoryId(), category_t.getLangId(), category_t.getName(), category_t.getDescription());
                ocProductService.addOcCategoryAndDesc(ocCategory, ocCateDesc_ch, ocCateDesc);
                
                productService.updateCategorySynCateId(category_t.getCode(), ocCategory.getCategoryId());
            }else{//同步过，更新
                OcCategory ocCategory = ocProductService.findOcCategory(cid_oc);
                if(ocCategory == null){//错误的同步过的类目ID
                    ocCategory = new OcCategory(new Date());
                    //中文
                    OcCategoryDescription ocCateDesc_ch = new OcCategoryDescription(ocCategory.getCategoryId(), SystemConstants.LANG_ID_CN, category_t.getName(), category_t.getDescription());
                    //原文
                    OcCategoryDescription ocCateDesc = new OcCategoryDescription(ocCategory.getCategoryId(), category_t.getLangId(), category_t.getName(), category_t.getDescription());
                    ocProductService.addOcCategoryAndDesc(ocCategory, ocCateDesc_ch, ocCateDesc);

                    productService.updateCategorySynCateId(category_t.getCode(), ocCategory.getCategoryId());
                }else{
                    OcCategoryDescription ocCateDesc = ocProductService.findOcCateDescByCateIdAndLang(
                            ocCategory.getCategoryId(), category_t.getLangId());
                    if(ocCateDesc == null){
                        ocCateDesc = new OcCategoryDescription(ocCategory.getCategoryId(), 
                                category_t.getLangId(), category_t.getName(), category_t.getDescription());
                        ocProductService.addOcCategoryDescription(ocCateDesc);
                    }else{
                        ocProductService.updateOcCateDesc(ocCategory.getCategoryId(), 
                                category_t.getLangId(), category_t.getName(), category_t.getDescription());
                    }
                }
            }
            productService.updateCategorySynStatus(category_t.getId(), SystemConstants.ENTITY_DATE_SYN_STATUS_SUCCESS);
            return SystemConstants.ENTITY_DATE_SYN_STATUS_SUCCESS;
        }catch(Exception e){
            productService.updateCategorySynStatus(category_t.getId(), SystemConstants.ENTITY_DATE_SYN_STATUS_FAILED);
            logger.error(e.getMessage(), e);
            return SystemConstants.ENTITY_DATE_SYN_STATUS_FAILED;
        }
    }
    
    public void synProductByCategory(Integer categoryId, boolean isAuto){
        List<Integer> productIds = productService.findAllProductIdsToSynByCateId(categoryId);
        if(productIds == null || productIds.size() < 1){
            return;
        }
        for(Integer pid : productIds){
            synProduct(pid, isAuto);
        }
    }
    
    public void synProduct(Integer proId, boolean isAuto){
        Product product_t = productService.findProduct(proId);
        //未采集或者正在采集中的产品不同步
        if(product_t.getNcStatus() == SystemConstants.NC_STATUS_NO || product_t.getNcStatus() == SystemConstants.NC_STATUS_RUN){
            return;
        }
        if(product_t.getSynStatus() == SystemConstants.ENTITY_DATE_SYN_STATUS_RUN){
            return;
        }
        if(isAuto && product_t.getSynStatus() == SystemConstants.ENTITY_DATE_SYN_STATUS_SUCCESS && 
                product_t.getSynTime().after(product_t.getModifyTime())){
            return;
        }
        Category category = productService.findCategory(product_t.getCategoryId());
        if(category.getSynCategoryId() == null){//类目未同步
            return;
        }
        OcProduct ocProduct = null;
        try{
            productService.updateProductSynStatus(product_t.getId(), SystemConstants.ENTITY_DATE_SYN_STATUS_RUN);
            String productDesc = dealProductDescImage(product_t.getDescription());
            Integer pid_oc = product_t.getSynProductId();
            if(pid_oc == null){//未同步过
                Double price = null;
                if(ValidateUtil.stringIsFloat(product_t.getPrice())){
                    price = Double.valueOf(product_t.getPrice());
                    Double priceRate = ocProductService.getPriceRate(product_t.getPriceUnit());
                    if(priceRate != null){
                        price = CalculateUtil.multiplyRound(price, priceRate, 2);
                    }
                }
                Double weight = null;
                if(ValidateUtil.stringIsFloat(product_t.getWeight())){
                    weight = Double.valueOf(product_t.getWeight());
                }
                Integer weightUnit = ocProductService.getWeightUnitId(product_t.getWeightUnit());
                
                ocProduct = new OcProduct(category.getCode(), "", price, weight, weightUnit);
                //中文
                OcProductDescription ocProDesc_ch = new OcProductDescription(ocProduct.getProductId(), SystemConstants.LANG_ID_CN, product_t.getName(), productDesc);
                //原文
                OcProductDescription ocProDesc = new OcProductDescription(ocProduct.getProductId(), product_t.getLangId(), product_t.getName(), productDesc);
                ocProductService.addOcProductAndDesc(ocProduct, ocProDesc_ch, ocProDesc);
                
                productService.updateProductSynProId(product_t.getCode(), ocProduct.getProductId());
            }else{//同步过，更新
                ocProduct = ocProductService.findOcProduct(pid_oc);
                if(ocProduct == null){//错误的同步过的类目ID
                    Double price = null;
                    if(ValidateUtil.stringIsFloat(product_t.getPrice())){
                        price = Double.valueOf(product_t.getPrice());
                        Double priceRate = ocProductService.getPriceRate(product_t.getPriceUnit());
                        if(priceRate != null){
                            price = CalculateUtil.multiplyRound(price, priceRate, 2);
                        }
                    }
                    Double weight = null;
                    if(ValidateUtil.stringIsFloat(product_t.getWeight())){
                        weight = Double.valueOf(product_t.getWeight());
                    }
                    Integer weightUnit = ocProductService.getWeightUnitId(product_t.getWeightUnit());
                    
                    ocProduct = new OcProduct(category.getCode(), "", price, weight, weightUnit);
                    //中文
                    OcProductDescription ocProDesc_ch = new OcProductDescription(ocProduct.getProductId(), SystemConstants.LANG_ID_CN, product_t.getName(), productDesc);
                    //原文
                    OcProductDescription ocProDesc = new OcProductDescription(ocProduct.getProductId(), product_t.getLangId(), product_t.getName(), productDesc);
                    ocProductService.addOcProductAndDesc(ocProduct, ocProDesc_ch, ocProDesc);
                    
                    productService.updateProductSynProId(product_t.getCode(), ocProduct.getProductId());
                }else{
                    OcProductDescription ocProDesc = ocProductService.findOcProductDesc(ocProduct.getProductId(), product_t.getLangId());
                    if(ocProDesc == null){
                        ocProDesc = new OcProductDescription(ocProduct.getProductId(), product_t.getLangId(), 
                                product_t.getName(), productDesc);
                        ocProductService.addOcProductDescription(ocProDesc);
                    }else{
                        ocProductService.updateOcProductDesc(ocProduct.getProductId(), product_t.getLangId(), 
                                product_t.getName(), productDesc);
                    }
                }
            }
            //同步商品与类目的关系
            OcProductToCategory opc = ocProductService.findOcProductToCategory(ocProduct.getProductId(), category.getSynCategoryId());
            if(opc == null){
                opc = new OcProductToCategory(ocProduct.getProductId(), category.getSynCategoryId());
                ocProductService.addOcProductToCategory(opc);
            }
            //同步图片
            boolean bo1 = synProductImage(product_t.getId(), ocProduct.getProductId(), ocProduct.getImage());
            //同步属性
            boolean bo2 = synProductAttr(product_t.getId(), ocProduct.getProductId(), product_t.getLangId());
            if(bo1 && bo2){
                productService.updateProductSynStatus(product_t.getId(), SystemConstants.ENTITY_DATE_SYN_STATUS_SUCCESS);
            }else{
                productService.updateProductSynStatus(product_t.getId(), SystemConstants.ENTITY_DATE_SYN_STATUS_FAILED);
            }
        }catch(Exception e){
            productService.updateProductSynStatus(product_t.getId(), SystemConstants.ENTITY_DATE_SYN_STATUS_FAILED);
            logger.error(e.getMessage(), e);
        }
    }
    
    public boolean synProductImage(Integer productId, Integer ocProductId, String mainImage){
        boolean bo = true;
        List<ProductImage> productImages = productService.findProductImageByProductId(productId);
        if(productImages != null && productImages.size() > 0){
            ProductImage productImage = productImages.get(0);
            int is = 0;
            if(mainImage == null || mainImage.trim().length() < 1 || !mainImage.equals(productImage.getLocalPath())){
                try{
                    FileUtils.madeFolderFromFile(ParseUtil.getOcImgRootPath() + productImage.getLocalPath());
                    FileUtils.backFile(new File(ParseUtil.getImgCenterRootPath() + productImage.getLocalPath()), 
                            "", ParseUtil.getOcImgRootPath() + productImage.getLocalPath(), false);
                    ocProductService.updateOcProductMainImage(ocProductId, SystemConstants.OC_IMAGE_ROOT_PATH + productImage.getLocalPath());
                    is = 1;
                }catch(Exception e){
                    bo = false;
                    logger.error(e.getMessage(), e);
                }
            }
            OcProductImage ocProductImage = null;
            for(int i = is; i < productImages.size(); i++){
                productImage = productImages.get(i);
                try{
                    FileUtils.madeFolderFromFile(ParseUtil.getOcImgRootPath() + productImage.getLocalPath());
                    FileUtils.backFile(new File(ParseUtil.getImgCenterRootPath() + productImage.getLocalPath()), 
                            "", ParseUtil.getOcImgRootPath() + productImage.getLocalPath(), false);
                    ocProductImage = ocProductService.findOcProductImage(ocProductId, SystemConstants.OC_IMAGE_ROOT_PATH + productImage.getLocalPath());
                    if(ocProductImage == null){
                        ocProductImage = new OcProductImage(ocProductId, SystemConstants.OC_IMAGE_ROOT_PATH + productImage.getLocalPath());
                        ocProductService.addOcProductImage(ocProductImage);
                    }else{
                        ocProductService.updateOcProductImage(ocProductImage.getProductImageId(), SystemConstants.OC_IMAGE_ROOT_PATH + productImage.getLocalPath());
                    }
                }catch(Exception e){
                    bo = false;
                    logger.error(e.getMessage(), e);
                }
            }
        }
        return bo;
    }
    
    public boolean synProductAttr(Integer productId, Integer ocProductId, Integer langId){
        List<ProductAttribute> atts = productService.findProductAttrByProductId(productId);
        boolean bo = true;
        if(atts != null){
            for(ProductAttribute a : atts){
                try{
                    boolean bot = synProductAttr(ocProductId, a);
                    if(!bot){
                        bo = false;
                    }
                }catch(Exception e){
                    bo = false;
                    logger.error(e.getMessage(), e);
                }
            }
        }
        return bo;
    }
    
    public boolean synProductAttr(Integer ocProductId, ProductAttribute attr){
        //验证属性
        Option option = null;
        boolean isUpdateOptionCode = false;
        if(attr.getNameCode() == null || attr.getNameCode().length() < 1){
            option = optionAndValueService.findOptionByNameAndLang(attr.getOptionName(), attr.getLangId());
            isUpdateOptionCode = true;
        }else{
            option = optionAndValueService.findOptionByNameCodeAndLang(attr.getNameCode(), attr.getLangId());
        }
        if(option == null || option.getOcOptionId() == null){
            return false;
        }
        //验证属性值
        OptionValue optionValue = null;
        boolean isUpdateOptionValueCode = false;
        if(attr.getValueCode() == null || attr.getValueCode().length() < 1){
            optionValue = optionAndValueService.findOptionValueByValueAndLang(option.getId(), attr.getOptionValue(), attr.getLangId());
            isUpdateOptionValueCode = true;
        }else{
            optionValue = optionAndValueService.findOptionValueByValueCodeAndLang(option.getId(), attr.getValueCode(), attr.getLangId());
        }
        if(optionValue == null || optionValue.getOcOptionValueId() == null){
            return false;
        }
        if(option.getOcOptionId() != optionValue.getOcOptionId()){
            logger.error("=========属性" + option.getId() + "与属性值" + optionValue.getId() + "不匹配");
            return false;
        }
        //更新属性
        if(isUpdateOptionCode){
            productService.updateAttrOptionCode(attr.getId(), option.getNameCode());
        }
        if(isUpdateOptionValueCode){
            productService.updateAttrOptionValueCode(attr.getId(), optionValue.getValueCode());
        }
        //同步属性
        OcProductOption ocProductOption = ocProductService.findOcProductOption(ocProductId, option.getOcOptionId());
        if(ocProductOption == null){
            ocProductOption = new OcProductOption(ocProductId, option.getOcOptionId(), null);
            ocProductService.addOcProductOption(ocProductOption);
        }
        OcProductOptionValue ocProductOptionValue = ocProductService.findOcProductOptionValue(
                ocProductOption.getProductOptionId(), optionValue.getOcOptionValueId());
        if(ocProductOptionValue == null){
            ocProductOptionValue = new OcProductOptionValue(ocProductOption.getProductOptionId(), ocProductId, option.getId(), optionValue.getOcOptionValueId());
            ocProductService.addOcProductOptionValue(ocProductOptionValue);
        }
        return true;
    }
    
    private String dealProductDescImage(String content){
        if(content == null || content.length() < 1){
            return content;
        }
        try {
            HtmlCleaner html = new HtmlCleaner();
            TagNode tagNode = html.clean(content);
            //取出所有图片
            Object[] imgs = tagNode.evaluateXPath("//img");
            if(imgs != null){
                String imgRootPath = ParseUtil.getImgCenterRootPath();
                String ocImgRootPath = ParseUtil.getOcImgRootPath();
                String ocServerHttp = ParseUtil.getOcServerHttp();
                TagNode n = null;
                String localPath = null;
                for(Object o : imgs){
                    if(o instanceof TagNode){
                        n = (TagNode)o;
                        localPath = n.getAttributeByName("localPath");
                        if(localPath != null){
                            FileUtils.madeFolderFromFile(ocImgRootPath + localPath);
                            FileUtils.backFile(new File(imgRootPath + localPath), "", ocImgRootPath + localPath, false);
                            n.setAttribute("src", ocServerHttp + SystemConstants.OC_IMAGE_DESC_ROOT_PATH + localPath);
                        }
                        n.removeAttribute("localPath");
                    }
                }
                content = html.getInnerHtml(tagNode);
            }
        }catch(Exception e){
            logger.error(e.getMessage(), e);
        }
        return content;
    }

    @Resource
    public void setProductService(ProductService productService) {
        this.productService = productService;
    }
    @Resource
    public void setOptionAndValueService(OptionAndValueService optionAndValueService) {
        this.optionAndValueService = optionAndValueService;
    }
    @Resource
    public void setOcProductService(OcProductService ocProductService) {
        this.ocProductService = ocProductService;
    }
}
